#include "MyFileSystem.h"
#include <dirent.h> // 文件系统库
#include <iostream>
#include <sys/stat.h> // 文件信息

MyFileSystem::MyFileSystem(const std::string &path)
{
    TreeNode *rootPath = new TreeNode(path);
    rootPath->Connect(tree.GetRoot()); // 绑到根目录下
    ExploreDir(rootPath, path);
}

void MyFileSystem::FindByFileName(const std::string &name)
{
    DoubleLinkList list = tree.FindByElement(name);
    // DoubleLinkList list = tree.FindByElement(name.substr(0,name.find(' ')));
    for (size_t i = 0; i < list.Size(); i++)
    {
        std::string path;
        TreeNode *node = (TreeNode *)*list.FindByIndex(i);
        path = node->GetData();
        while (node->Getparent() != nullptr && node->Getparent() != tree.GetRoot()) // 向上层找
        {
            path = node->Getparent()->GetData() + "/" + path;
            node = node->Getparent();
        }
        std::cout << path << std::endl;
    }
}

std::string DoubleToStr(double n, int fixed = 2) // 保留的位数
{
    std::string s = std::to_string(n);
    return s.substr(0, s.find('.') + fixed + 1);
}

std::string Transform(long size) // 长整型转化为字符串
{
    // char s[100];
    // int i = 0;
    // while (size > 0)
    // {
    //     s[i++] = size % 10 + '0';
    //     size /= 10;
    // }
    // std::string result;
    // for (int index = i-1; index >= 0; index--)
    // {
    //     result += s[index];
    // }
    // return result;
    if (size < 1024)
        return std::to_string(size) + "B"; // std::to_string这个可以直接转
    else if (size < 1024 * 1024)
        return DoubleToStr(1.0 * size / 1024) + "KB";
    else if (size < 1024 * 1024 * 1024)
        return DoubleToStr(1.0 * size / 1024 / 1024) + "MB";
    else
        return DoubleToStr(1.0 * size / 1024 / 1024 / 1024) + "GB";
}

void MyFileSystem::ExploreDir(TreeNode *parent, const std::string &path)
{
    DIR *dir = opendir(path.c_str()); // 打开一个文件夹
    if (dir == nullptr)
    {
        std::cout << "文件夹路径有误!\n";
        return;
    }
    dirent *d = nullptr; // 读取文件夹下的文件
    while ((d = readdir(dir)) != nullptr)
    {
        std::string dname(d->d_name);
        if (dname != "." && dname != "..")
        {
            // TreeNode *node = new TreeNode(d->d_name);
            TreeNode *node = new TreeNode(dname);
            node->Connect(parent);
            if (d->d_type == DT_DIR)
            {
                ExploreDir(node, path + "/" + dname); // path + "/" + dname下一层
            }
            else
            {
                struct stat s;
                stat((path + "/" + dname).c_str(), &s); // 根据路径获取文件信息
                char name[512] = {0};
                // std::cout << s.st_size << std::endl;
                sprintf(name, "%-30s size:%s", dname.c_str(), Transform(s.st_size).c_str());
                // node->SetData(dname + "  size: " + Transform(s.st_size));
                node->SetData(name);
            }
        }
    }
    closedir(dir);
}
